package com.google.code.gossip;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * This object represents the settings used when starting the gossip service.
 * 
 * @author harmenw
 */
public class StartupSettings {
	
	/** The port to start the gossip service on. */
	private int _port;
	
	/** The logging level of the gossip service. */
	private int _logLevel;
	
	/** The gossip settings used at startup. */
	private GossipSettings _gossipSettings;
	
	/** The list with gossip members to start with. */
	private ArrayList<GossipMember> _gossipMembers;
	
	/**
	 * Constructor.
	 * @param port The port to start the service on.
	 */
	public StartupSettings(int port, int logLevel) {
		this(port, logLevel, new GossipSettings());
	}
	
	/**
	 * Constructor.
	 * @param port The port to start the service on.
	 */
	public StartupSettings(int port, int logLevel, GossipSettings gossipSettings) {
		_port = port;
		_logLevel = logLevel;
		_gossipSettings = gossipSettings;
		_gossipMembers = new ArrayList<GossipMember>();
	}
	
	/**
	 * Set the port of the gossip service.
	 * @param port The port for the gossip service.
	 */
	public void setPort(int port) {
		_port = port;
	}
	
	/**
	 * Get the port for the gossip service.
	 * @return The port of the gossip service.
	 */
	public int getPort() {
		return _port;
	}
	
	/**
	 * Set the log level of the gossip service.
	 * @param logLevel The log level({LogLevel}).
	 */
	public void setLogLevel(int logLevel) {
		_logLevel = logLevel;
	}
	
	/**
	 * Get the log level of the gossip service.
	 * @return The log level.
	 */
	public int getLogLevel() {
		return _logLevel;
	}
	
	/**
	 * Get the GossipSettings.
	 * @return The GossipSettings object.
	 */
	public GossipSettings getGossipSettings() {
		return _gossipSettings;
	}
	
	/**
	 * Add a gossip member to the list of members to start with.
	 * @param member The member to add.
	 */
	public void addGossipMember(GossipMember member) {
		_gossipMembers.add(member);
	}
	
	/**
	 * Get the list with gossip members.
	 * @return The gossip members.
	 */
	public ArrayList<GossipMember> getGossipMembers() {
		return _gossipMembers;
	}
	
	/**
	 * Parse the settings for the gossip service from a JSON file.
	 * @param jsonFile The file object which refers to the JSON config file.
	 * @return The StartupSettings object with the settings from the config file.
	 * @throws JSONException Thrown when the file is not well-formed JSON.
	 * @throws FileNotFoundException Thrown when the file cannot be found.
	 * @throws IOException Thrown when reading the file gives problems.
	 */
	public static StartupSettings fromJSONFile(File jsonFile) throws JSONException, FileNotFoundException, IOException {
		// Read the file to a String.
		BufferedReader br = new BufferedReader(new FileReader(jsonFile));
		StringBuffer buffer = new StringBuffer();
		String line;
		while((line = br.readLine()) != null) {
			buffer.append(line.trim());
		}
		
		// Lets parse the String as JSON.
		JSONObject jsonObject = new JSONArray(buffer.toString()).getJSONObject(0);
		
		// Now get the port number.
		int port = jsonObject.getInt("port");

		// Get the log level from the config file.
		int logLevel = LogLevel.fromString(jsonObject.getString("log_level"));
		
		// Get the gossip_interval from the config file.
		int gossipInterval = jsonObject.getInt("gossip_interval");
		
		// Get the cleanup_interval from the config file.
		int cleanupInterval = jsonObject.getInt("cleanup_interval");
		
		System.out.println("Config [port: " + port + ", log_level: " + logLevel + ", gossip_interval: " + gossipInterval + ", cleanup_interval: " + cleanupInterval + "]");
		
		// Initiate the settings with the port number.
		StartupSettings settings = new StartupSettings(port, logLevel, new GossipSettings(gossipInterval, cleanupInterval));
		
		// Now iterate over the members from the config file and add them to the settings.
		System.out.print("Config-members [");
		JSONArray membersJSON = jsonObject.getJSONArray("members");
		for (int i=0; i<membersJSON.length(); i++) {
			JSONObject memberJSON = membersJSON.getJSONObject(i);
			RemoteGossipMember member = new RemoteGossipMember(memberJSON.getString("host"), memberJSON.getInt("port"));
			settings.addGossipMember(member);
			System.out.print(member.getAddress());
			if (i < (membersJSON.length() - 1))
				System.out.print(", ");
		}
		System.out.println("]");
		
		// Return the created settings object.
		return settings;
	}
}
